<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web版轴承监控系统 - 改进版</title>
    
    <!-- 引入Chart.js用于图表显示 -->
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://cdn.socket.io/4.5.0/socket.io.min.js"></script>
    
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1600px;
            margin: 0 auto;
            background: rgba(255, 255, 255, 0.95);
            border-radius: 15px;
            box-shadow: 0 20px 40px rgba(0,0,0,0.1);
            overflow: hidden;
        }
        
        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }
        
        .header h1 {
            font-size: 2.5em;
            margin-bottom: 10px;
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }
        
        .header .info {
            display: flex;
            justify-content: space-around;
            margin-top: 20px;
            flex-wrap: wrap;
        }
        
        .info-item {
            background: rgba(255,255,255,0.2);
            padding: 10px 20px;
            border-radius: 25px;
            margin: 5px;
            font-weight: 500;
        }
        
        /* 启动检测结果样式 */
        .startup-tests {
            background: rgba(255,255,255,0.1);
            margin: 20px;
            padding: 20px;
            border-radius: 10px;
            border: 2px solid rgba(255,255,255,0.2);
        }
        
        .startup-tests h3 {
            margin-bottom: 15px;
            font-size: 1.2em;
        }
        
        .test-results {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 10px;
        }
        
        .test-item {
            display: flex;
            align-items: center;
            padding: 8px 12px;
            background: rgba(255,255,255,0.1);
            border-radius: 8px;
            font-size: 0.9em;
        }
        
        .test-icon {
            margin-right: 8px;
            font-size: 1.2em;
        }
        
        .test-status-all_passed {
            border-left: 4px solid #51cf66;
        }
        
        .test-status-partial_passed {
            border-left: 4px solid #ff922b;
        }
        
        .test-status-all_failed {
            border-left: 4px solid #ff6b6b;
        }
        
        .test-status-not_tested {
            border-left: 4px solid #868e96;
        }
        
        .dashboard {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
            gap: 20px;
            padding: 20px;
        }
        
        .card {
            background: white;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.08);
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }
        
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 25px rgba(0,0,0,0.15);
        }
        
        .card h3 {
            color: #333;
            margin-bottom: 15px;
            font-size: 1.3em;
            border-bottom: 2px solid #667eea;
            padding-bottom: 8px;
        }
        
        /* 大卡片样式 - 用于振动XYZ和音频波形 */
        .card-large {
            grid-column: 1 / -1;
        }
        
        .card-half {
            grid-column: span 1;
        }
        
        .status-grid {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 15px;
        }
        
        .status-item {
            background: #f8f9ff;
            padding: 15px;
            border-radius: 8px;
            border-left: 4px solid #667eea;
        }
        
        .status-value {
            font-size: 1.8em;
            font-weight: bold;
            color: #333;
            margin-top: 5px;
        }
        
        .status-label {
            color: #666;
            font-size: 0.9em;
        }
        
        .chart-container {
            position: relative;
            height: 300px;
            margin: 15px 0;
        }
        
        .chart-container-large {
            position: relative;
            height: 400px;
            margin: 15px 0;
        }
        
        .controls {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
            margin: 15px 0;
        }
        
        .btn {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 25px;
            cursor: pointer;
            font-weight: 500;
            transition: all 0.3s ease;
            text-decoration: none;
            display: inline-block;
        }
        
        .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
        }
        
        .btn:active {
            transform: translateY(0);
        }
        
        .connection-status {
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 10px 20px;
            border-radius: 25px;
            color: white;
            font-weight: 500;
            z-index: 1000;
            transition: all 0.3s ease;
        }
        
        .connected {
            background: #51cf66;
        }
        
        .disconnected {
            background: #ff6b6b;
        }
        
        .photos-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
            gap: 15px;
            max-height: 400px;
            overflow-y: auto;
        }
        
        .photo-item {
            position: relative;
            border-radius: 8px;
            overflow: hidden;
            box-shadow: 0 3px 10px rgba(0,0,0,0.1);
            transition: transform 0.3s ease;
        }
        
        .photo-item:hover {
            transform: scale(1.05);
        }
        
        .photo-item img {
            width: 100%;
            height: 120px;
            object-fit: cover;
        }
        
        .photo-timestamp {
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            background: linear-gradient(transparent, rgba(0,0,0,0.8));
            color: white;
            padding: 5px;
            font-size: 0.8em;
            text-align: center;
        }
        
        .anomaly-list {
            max-height: 300px;
            overflow-y: auto;
        }
        
        .anomaly-item {
            background: #fff5f5;
            border-left: 4px solid #ff6b6b;
            padding: 10px;
            margin: 5px 0;
            border-radius: 5px;
        }
        
        .anomaly-item.medium {
            background: #fff8f0;
            border-color: #ff922b;
        }
        
        .anomaly-item.low {
            background: #f0fff4;
            border-color: #51cf66;
        }
        
        .loading {
            text-align: center;
            padding: 20px;
            color: #666;
        }
        
        .spinner {
            border: 4px solid #f3f3f3;
            border-top: 4px solid #667eea;
            border-radius: 50%;
            width: 40px;
            height: 40px;
            animation: spin 1s linear infinite;
            margin: 0 auto 20px;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .alert {
            position: fixed;
            top: 80px;
            right: 20px;
            max-width: 300px;
            padding: 15px;
            border-radius: 8px;
            color: white;
            font-weight: 500;
            z-index: 1001;
            transform: translateX(100%);
            transition: transform 0.3s ease;
        }
        
        .alert.show {
            transform: translateX(0);
        }
        
        .alert-success {
            background: #51cf66;
        }
        
        .alert-error {
            background: #ff6b6b;
        }
        
        .alert-warning {
            background: #ff922b;
        }
        
        @media (max-width: 768px) {
            .dashboard {
                grid-template-columns: 1fr;
            }
            
            .header .info {
                flex-direction: column;
                align-items: center;
            }
            
            .controls {
                justify-content: center;
            }
            
            .test-results {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>
<body>
    <div id="connection-status" class="connection-status disconnected">
        🔴 连接中...
    </div>
    
    <div id="alert-container"></div>
    
    <div class="container">
        <div class="header">
            <h1>🔧 Web版轴承监控系统 - 改进版</h1>
            <div class="info">
                <div class="info-item">📋 测试: {{ test_name }}</div>
                <div class="info-item">👤 操作员: {{ operator }}</div>
                <div class="info-item">⚙️ 轴承型号: {{ bearing_model }}</div>
                <div class="info-item" id="current-time">🕒 加载中...</div>
            </div>
            
            <!-- 启动检测结果 -->
            <div class="startup-tests" id="startup-tests-container">
                <h3>🔍 启动模块检测结果</h3>
                <div id="startup-tests-summary" class="test-item test-status-not_tested">
                    <span class="test-icon">⏳</span>
                    <span>正在加载检测结果...</span>
                </div>
            </div>
        </div>
        
        <div class="dashboard">
            <!-- 实时状态面板 -->
            <div class="card">
                <h3>📊 实时状态</h3>
                <div class="status-grid">
                    <div class="status-item">
                        <div class="status-label">温度 (°C)</div>
                        <div class="status-value" id="current-temp">--</div>
                    </div>
                    <div class="status-item">
                        <div class="status-label">振动强度 (g)</div>
                        <div class="status-value" id="current-vibration">--</div>
                    </div>
                    <div class="status-item">
                        <div class="status-label">声音异常分数</div>
                        <div class="status-value" id="current-audio">--</div>
                    </div>
                    <div class="status-item">
                        <div class="status-label">异常事件</div>
                        <div class="status-value" id="anomaly-count">0</div>
                    </div>
                </div>
            </div>
            
            <!-- 温度图表 -->
            <div class="card">
                <h3>🌡️ 温度监控</h3>
                <div class="chart-container">
                    <canvas id="tempChart"></canvas>
                </div>
            </div>
            
            <!-- XYZ三轴振动图表 - 大卡片 -->
            <div class="card card-large">
                <h3>📈 XYZ三轴振动监控</h3>
                <div class="chart-container-large">
                    <canvas id="vibrationXYZChart"></canvas>
                </div>
            </div>
            
            <!-- 声音波形图表 - 大卡片 -->
            <div class="card card-large">
                <h3>🔊 声音波形监控 (类似Audacity)</h3>
                <div class="chart-container-large">
                    <canvas id="audioWaveformChart"></canvas>
                </div>
            </div>
            
            <!-- 拍照控制 -->
            <div class="card">
                <h3>📸 拍照控制</h3>
                <div class="controls">
                    <button class="btn" onclick="takePhoto()">📷 立即拍照</button>
                    <button class="btn" onclick="refreshPhotos()">🔄 刷新照片</button>
                </div>
                <div id="photos-container" class="loading">
                    <div class="spinner"></div>
                    <div>加载照片中...</div>
                </div>
            </div>
            
            <!-- 异常记录 -->
            <div class="card">
                <h3>⚠️ 异常记录</h3>
                <div id="anomaly-list" class="anomaly-list">
                    <div class="loading">
                        <div class="spinner"></div>
                        <div>加载异常记录中...</div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 全局变量
        let socket;
        let charts = {};
        let isConnected = false;
        let startupTestResults = null;
        
        // 数据存储 - 使用线性坐标轴
        const dataBuffer = {
            temperature: [],
            vibration: [],
            audio: [],
            vibrationXYZ: [], // XYZ三轴数据
            audioWaveform: [], // 音频波形数据
            maxLength: 100
        };
        
        let dataIndex = 0; // 线性数据索引
        
        // 初始化
        document.addEventListener('DOMContentLoaded', function() {
            initializeSocket();
            initializeCharts();
            updateTime();
            setInterval(updateTime, 1000);
            loadInitialData();
            
            // 定期更新XYZ和波形数据
            setInterval(updateVibrationXYZ, 2000);
            setInterval(updateAudioWaveform, 3000);
        });
        
        // 初始化Socket连接
        function initializeSocket() {
            socket = io();
            
            socket.on('connect', function() {
                isConnected = true;
                updateConnectionStatus(true);
                showAlert('WebSocket连接成功', 'success');
            });
            
            socket.on('disconnect', function() {
                isConnected = false;
                updateConnectionStatus(false);
                showAlert('WebSocket连接断开', 'error');
            });
            
            socket.on('startup_tests', function(data) {
                updateStartupTestResults(data);
            });
            
            socket.on('temperature_data', function(data) {
                updateTemperatureData(data);
            });
            
            socket.on('vibration_data', function(data) {
                updateVibrationData(data);
            });
            
            socket.on('audio_data', function(data) {
                updateAudioData(data);
            });
            
            socket.on('anomaly_alert', function(data) {
                addAnomalyAlert(data);
                showAlert(`检测到异常: ${data.description}`, 'warning');
            });
            
            socket.on('new_photo', function(data) {
                showAlert('新照片已拍摄', 'success');
                refreshPhotos();
            });
        }
        
        // 更新启动测试结果
        function updateStartupTestResults(testResults) {
            startupTestResults = testResults;
            
            // 更新摘要
            const summaryEl = document.getElementById('startup-tests-summary');
            const statusIcons = {
                'all_passed': '✅',
                'partial_passed': '⚠️',
                'all_failed': '❌',
                'not_tested': '⏳'
            };
            
            summaryEl.className = `test-item test-status-${testResults.status}`;
            summaryEl.innerHTML = `
                <span class="test-icon">${statusIcons[testResults.status]}</span>
                <span>${testResults.message}</span>
            `;
        }
        
        // 初始化图表 - 包含新的XYZ和波形图表
        function initializeCharts() {
            const chartConfig = {
                type: 'line',
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    animation: {
                        duration: 0 // 禁用动画以提高性能
                    },
                    scales: {
                        x: {
                            type: 'linear',
                            title: {
                                display: true,
                                text: '时间点'
                            }
                        },
                        y: {
                            beginAtZero: true,
                            title: {
                                display: true
                            }
                        }
                    },
                    plugins: {
                        legend: {
                            display: false
                        }
                    }
                }
            };
            
            // 温度图表
            const tempConfig = JSON.parse(JSON.stringify(chartConfig));
            tempConfig.data = {
                datasets: [{
                    label: '温度',
                    data: [],
                    borderColor: 'rgb(255, 99, 132)',
                    backgroundColor: 'rgba(255, 99, 132, 0.1)',
                    tension: 0.4,
                    pointRadius: 1
                }]
            };
            tempConfig.options.scales.y.title.text = '温度 (°C)';
            charts.temperature = new Chart(document.getElementById('tempChart'), tempConfig);
            
            // XYZ三轴振动图表
            const vibrationXYZConfig = JSON.parse(JSON.stringify(chartConfig));
            vibrationXYZConfig.data = {
                datasets: [
                    {
                        label: 'X轴',
                        data: [],
                        borderColor: 'rgb(255, 99, 132)',
                        backgroundColor: 'rgba(255, 99, 132, 0.1)',
                        tension: 0.4,
                        pointRadius: 1
                    },
                    {
                        label: 'Y轴',
                        data: [],
                        borderColor: 'rgb(54, 162, 235)',
                        backgroundColor: 'rgba(54, 162, 235, 0.1)',
                        tension: 0.4,
                        pointRadius: 1
                    },
                    {
                        label: 'Z轴',
                        data: [],
                        borderColor: 'rgb(75, 192, 192)',
                        backgroundColor: 'rgba(75, 192, 192, 0.1)',
                        tension: 0.4,
                        pointRadius: 1
                    }
                ]
            };
            vibrationXYZConfig.options.scales.y.title.text = '加速度 (g)';
            vibrationXYZConfig.options.plugins.legend.display = true;
            charts.vibrationXYZ = new Chart(document.getElementById('vibrationXYZChart'), vibrationXYZConfig);
            
            // 声音波形图表 (类似Audacity)
            const audioWaveformConfig = JSON.parse(JSON.stringify(chartConfig));
            audioWaveformConfig.data = {
                datasets: [{
                    label: '声音波形',
                    data: [],
                    borderColor: 'rgb(255, 206, 84)',
                    backgroundColor: 'rgba(255, 206, 84, 0.3)',
                    tension: 0.1,
                    pointRadius: 0,
                    fill: true
                }]
            };
            audioWaveformConfig.options.scales.y.title.text = '振幅';
            audioWaveformConfig.options.scales.y.min = -1;
            audioWaveformConfig.options.scales.y.max = 1;
            audioWaveformConfig.options.scales.x.title.text = '样本点';
            charts.audioWaveform = new Chart(document.getElementById('audioWaveformChart'), audioWaveformConfig);
        }
        
        // 更新连接状态
        function updateConnectionStatus(connected) {
            const statusEl = document.getElementById('connection-status');
            if (connected) {
                statusEl.textContent = '🟢 已连接';
                statusEl.className = 'connection-status connected';
            } else {
                statusEl.textContent = '🔴 已断开';
                statusEl.className = 'connection-status disconnected';
            }
        }
        
        // 更新时间
        function updateTime() {
            const now = new Date();
            document.getElementById('current-time').textContent = 
                `🕒 ${now.toLocaleString('zh-CN')}`;
        }
        
        // 更新温度数据
        function updateTemperatureData(data) {
            // 更新实时显示
            document.getElementById('current-temp').textContent = data.temperature.toFixed(1);
            
            // 添加到数据缓冲区
            dataBuffer.temperature.push({
                x: dataIndex,
                y: data.temperature
            });
            
            // 保持数据长度
            if (dataBuffer.temperature.length > dataBuffer.maxLength) {
                dataBuffer.temperature.shift();
                // 重新调整所有数据的x坐标
                dataBuffer.temperature.forEach((point, index) => {
                    point.x = index;
                });
            }
            
            // 更新图表
            charts.temperature.data.datasets[0].data = dataBuffer.temperature;
            charts.temperature.update('none');
            
            dataIndex++;
        }
        
        // 更新振动数据
        function updateVibrationData(data) {
            // 更新实时显示
            document.getElementById('current-vibration').textContent = data.magnitude.toFixed(3);
        }
        
        // 更新声音数据
        function updateAudioData(data) {
            // 更新实时显示
            document.getElementById('current-audio').textContent = data.score.toFixed(3);
        }
        
        // 更新XYZ三轴振动数据
        function updateVibrationXYZ() {
            fetch('/api/vibration_xyz?count=50')
            .then(response => response.json())
            .then(data => {
                if (data && data.length > 0) {
                    const xData = [];
                    const yData = [];
                    const zData = [];
                    
                    data.forEach((point, index) => {
                        xData.push({x: index, y: point.ax});
                        yData.push({x: index, y: point.ay});
                        zData.push({x: index, y: point.az});
                    });
                    
                    charts.vibrationXYZ.data.datasets[0].data = xData;
                    charts.vibrationXYZ.data.datasets[1].data = yData;
                    charts.vibrationXYZ.data.datasets[2].data = zData;
                    charts.vibrationXYZ.update('none');
                }
            })
            .catch(error => {
                console.error('XYZ振动数据更新错误:', error);
            });
        }
        
        // 更新声音波形数据
        function updateAudioWaveform() {
            fetch('/api/audio_waveform?count=1')
            .then(response => response.json())
            .then(data => {
                if (data && data.length > 0 && data[0].waveform) {
                    const waveformData = [];
                    data[0].waveform.forEach((amplitude, index) => {
                        waveformData.push({x: index, y: amplitude});
                    });
                    
                    charts.audioWaveform.data.datasets[0].data = waveformData;
                    charts.audioWaveform.update('none');
                }
            })
            .catch(error => {
                console.error('音频波形数据更新错误:', error);
            });
        }
        
        // 拍照功能
        function takePhoto() {
            fetch('/api/take_photo', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showAlert('拍照成功!', 'success');
                    setTimeout(refreshPhotos, 1000);
                } else {
                    showAlert('拍照失败: ' + data.message, 'error');
                }
            })
            .catch(error => {
                showAlert('拍照请求失败', 'error');
                console.error('拍照错误:', error);
            });
        }
        
        // 刷新照片
        function refreshPhotos() {
            const container = document.getElementById('photos-container');
            container.innerHTML = '<div class="loading"><div class="spinner"></div><div>加载照片中...</div></div>';
            
            fetch('/api/photos')
            .then(response => response.json())
            .then(photos => {
                if (photos.length === 0) {
                    container.innerHTML = '<div style="text-align: center; color: #666; padding: 20px;">暂无照片</div>';
                    return;
                }
                
                const photosGrid = document.createElement('div');
                photosGrid.className = 'photos-grid';
                
                photos.forEach(photo => {
                    const photoItem = document.createElement('div');
                    photoItem.className = 'photo-item';
                    
                    photoItem.innerHTML = `
                        <img src="${photo.path}" alt="照片" onclick="showPhotoModal('${photo.path}')">
                        <div class="photo-timestamp">${photo.created}</div>
                    `;
                    
                    photosGrid.appendChild(photoItem);
                });
                
                container.innerHTML = '';
                container.appendChild(photosGrid);
            })
            .catch(error => {
                container.innerHTML = '<div style="text-align: center; color: #ff6b6b; padding: 20px;">照片加载失败</div>';
                console.error('照片加载错误:', error);
            });
        }
        
        // 加载初始数据
        function loadInitialData() {
            // 加载系统状态
            fetch('/api/status')
            .then(response => response.json())
            .then(status => {
                document.getElementById('anomaly-count').textContent = status.anomaly_count;
                
                // 加载启动测试结果
                if (status.startup_tests) {
                    updateStartupTestResults(status.startup_tests);
                }
            });
            
            // 加载启动测试结果
            fetch('/api/test_results')
            .then(response => response.json())
            .then(results => {
                updateStartupTestResults(results);
            });
            
            // 加载异常记录
            loadAnomalies();
            
            // 加载照片
            refreshPhotos();
        }
        
        // 加载异常记录
        function loadAnomalies() {
            const container = document.getElementById('anomaly-list');
            container.innerHTML = '<div class="loading"><div class="spinner"></div><div>加载异常记录中...</div></div>';
            
            fetch('/api/anomalies')
            .then(response => response.json())
            .then(anomalies => {
                if (anomalies.length === 0) {
                    container.innerHTML = '<div style="text-align: center; color: #51cf66; padding: 20px;">✅ 暂无异常记录</div>';
                    return;
                }
                
                container.innerHTML = '';
                anomalies.forEach(anomaly => {
                    addAnomalyToList(anomaly);
                });
            })
            .catch(error => {
                container.innerHTML = '<div style="text-align: center; color: #ff6b6b; padding: 20px;">异常记录加载失败</div>';
                console.error('异常记录加载错误:', error);
            });
        }
        
        // 添加异常到列表
        function addAnomalyToList(anomaly) {
            const container = document.getElementById('anomaly-list');
            const anomalyItem = document.createElement('div');
            anomalyItem.className = `anomaly-item ${anomaly.severity}`;
            
            anomalyItem.innerHTML = `
                <div style="display: flex; justify-content: space-between; align-items: center;">
                    <div>
                        <strong>${anomaly.type.toUpperCase()}</strong>
                        <div style="margin: 5px 0; color: #666;">${anomaly.description}</div>
                        <small>${anomaly.timestamp}</small>
                    </div>
                    <div style="text-align: right; font-size: 0.9em;">
                        ${anomaly.temperature > 0 ? `温度: ${anomaly.temperature.toFixed(1)}°C<br>` : ''}
                        ${anomaly.vibration > 0 ? `振动: ${anomaly.vibration.toFixed(3)}g<br>` : ''}
                        ${anomaly.audio_score > 0 ? `声音: ${anomaly.audio_score.toFixed(3)}` : ''}
                    </div>
                </div>
            `;
            
            container.insertBefore(anomalyItem, container.firstChild);
            
            // 限制显示数量
            while (container.children.length > 20) {
                container.removeChild(container.lastChild);
            }
        }
        
        // 添加异常警报
        function addAnomalyAlert(anomaly) {
            addAnomalyToList(anomaly);
            
            // 更新异常计数
            const currentCount = parseInt(document.getElementById('anomaly-count').textContent);
            document.getElementById('anomaly-count').textContent = currentCount + 1;
        }
        
        // 显示提示信息
        function showAlert(message, type) {
            const alertContainer = document.getElementById('alert-container');
            const alert = document.createElement('div');
            alert.className = `alert alert-${type}`;
            alert.textContent = message;
            
            alertContainer.appendChild(alert);
            
            // 显示动画
            setTimeout(() => {
                alert.classList.add('show');
            }, 100);
            
            // 自动隐藏
            setTimeout(() => {
                alert.classList.remove('show');
                setTimeout(() => {
                    if (alert.parentNode) {
                        alert.parentNode.removeChild(alert);
                    }
                }, 300);
            }, 3000);
        }
        
        // 显示照片模态框
        function showPhotoModal(photoPath) {
            const modal = document.createElement('div');
            modal.style.cssText = `
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: rgba(0,0,0,0.8);
                display: flex;
                justify-content: center;
                align-items: center;
                z-index: 2000;
                cursor: pointer;
            `;
            
            const img = document.createElement('img');
            img.src = photoPath;
            img.style.cssText = `
                max-width: 90%;
                max-height: 90%;
                border-radius: 10px;
                box-shadow: 0 10px 30px rgba(0,0,0,0.5);
            `;
            
            modal.appendChild(img);
            document.body.appendChild(modal);
            
            modal.addEventListener('click', () => {
                document.body.removeChild(modal);
            });
        }
        
        // 页面卸载时清理资源
        window.addEventListener('beforeunload', function() {
            if (socket) {
                socket.disconnect();
            }
        });
    </script>
</body>
</html>